#!/usr/bin/env python
# coding: utf-8

############################################################################
#                   2013/03/07  Ver 1.0                                    #
#Author:FANCL                                                              #
#Release note:                                                             #
############################################################################


import os
import re
import shutil
import zipfile
import time
import datetime
import string
from onshs.ne.tnxxx.tnxxxcfg_basecase import *


log_node_prefix = "wa_cpu_iic_repair_remove"
log_node_fail = log_node_prefix+r"_fail"
log_node_normal = log_node_prefix+r"_normal"
log_node_success = log_node_prefix+r"_success"
log_node_summary = log_node_prefix +r"_summary"

log_connect_fail = "connect ip:%s failed\n"
log_connect_slot_fail = "connect ip:%s slot:%d failed\n"
log_cpu_no_need = "ip:%s . slot %d opca donn't need  CPU repair removed. Active opca is slot:%d.\n"
log_cpu_fail = "ip:%s . slot %d opca cpu repair removed failed. Active opca is slot:%d.\n"
log_cpu_success = "ip:%s . slot %d opca cpu repair removed success. Active opca is slot:%d.\n"
log_iic_fail = "ip:%s . slot %d  opca  IIC disabled removed failed. Active opca is slot:%d.\n"
log_iic_success = "ip:%s . slot %d opca IIC disabled removed success. Active opca is slot:%d.\n"
log_cpu_iic_success = "ip:%s . CPU repaired removed success and  IIC disabled removed success.\n"
log_cpu_iic_fail = "ip:%s . CPU repaired removed fail and  IIC disabled removed fail.\n"

class TestCase(TnxxxCfg_BaseCase):
    """
    TestCase
    """
    OPTIONS = [
        {
            'opt' : '--cfgfile',
            'dest': 'cfgfile',
            'metavar' : 'CFGFILE',
            'help' : 'the file of ip list configuration',
            'required' : False,
            'default' : "ip.txt"
        },
        {
            'opt' : '--path',
            'dest': 'path',
            'metavar' : 'PATH',
            'help' : 'the directory of ip.txt',
            'required' : False,
            'default' : "D:\iplist"
        },
        {
            'opt' : '--interval',
            'dest': 'interval',
            'metavar' : 'INTERVAL',
            'help' : 'the time of sleep', 
            'required' : False,
            'default' : "600"
        },
        {
            'opt' : '--ipsource',
            'dest': 'ipsource',
            'metavar' : 'IPSOURCE',
            'help' : 'the source of ip',
            'required' : False,
            'default' : "folder"
        },
        {
            'opt' : '--sleeptime',
            'dest': 'sleeptime',
            'metavar' : 'SLEEPTIME',
            'help' : 'the sleep time of every operation',
            'required' : False,
            'default' : 10
        },
        {
            'opt' : '--quit',
            'dest': 'quit',
            'metavar' : 'QUIT',
            'help' : 'whether quit the script if the ip folder is empty',
            'required' : False,
            'default' : "False"
        },
        {
            'opt' : '--delete',
            'dest': 'delete',
            'metavar' : 'DELETE',
            'help' : 'whether delete the ip.txt which is repaired fail',
            'required' : False,
            'default' : "False"
        }
    ]
    
        #初始化信息
    def info_init(self):
        self.info_dic = {}  

        return True
    
    #得到IPLIST
    def get_iplist_from_folder(self):
        iplist_filted = []
        iplist = []
        
        if not os.path.isdir(self.options.path):
            #记录目录不存在
            return iplist
        else:
            #得到文件下的文件列表
            iplist_filted = os.listdir(self.options.path)
            
            #字符串截取，保留IP地址
            for ip in iplist_filted:
                iplist.append(ip[0:len(ip[0])-5])
                
        return iplist
    
    def get_iplist_from_file(self):
        iplist_filted = []                
        if os.path.isfile(os.getcwd()+r'/'+ self.iplistfile):
            iplist = open(os.getcwd()+r'/'+ self.iplistfile)
            #self.info_show(log_node_info, "The iplist file %s is existed."%(self.iplistfile)) 
        else:
            self.info_show(self.log_node_fail, self.log_file_not_existed%(self.iplistfile))            
            return iplist_filted 
        
        for line in iplist:
            if re.match(r'^\s*$', line) is not None : continue # 忽略空白行
            if re.match(r'^\s*#', line) is not None : continue # 忽略注释行            
            iplist_filted.append(line.strip('\n'))        
            
        iplist.close()
        
        return iplist_filted
    
    #跟LOG相关函数
    def info_show(self, node, info):
        if not self.info_dic.has_key(node):
            self.info_dic[node] = ""
        self.info_dic[node] += info + '\n'
        return True

    def info_file_clear(self):
        if os.path.exists(os.getcwd()+r'/log'):
            shutil.rmtree(os.getcwd()+r'/log')
        
        return True    
    
    def info_file_save(self):
        path = os.getcwd()+'//'
        
        for node in self.info_dic:
            info_list = open(path+node+'_'+self.worktime+'.txt','a')            
            info_list.write(self.info_dic[node])
            info_list.close()
        return True
        
    def getMasterPPC(self):
        slotList = []
        cmd = r'''$.dbgcli.0.Cmd "queryasyn valid 1, NeStat, (MasterPPC), *"'''
        rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if rtn_str == '':
            self.info_show(log_node_fail, log_connect_fail%(self.get_ne_ip(0)))      
            return slotList 
        slotList = re.findall(r"{\r\n  (\d)\r\n}", rtn_str, 0)
        
        return (int)(slotList[0])

    def my_sleep(self, seconds, interval):
        
        tempseconds = seconds
        for i in range(seconds/interval):
            SECONDS = tempseconds%60
            MINUTES = (tempseconds/60)%60
            HOURS = (tempseconds/3600)%24
            DAYS = (tempseconds/(3600*24))
            print "Countdown = %2d DAYS  %2d H:%2d M:%2d S" % (DAYS, HOURS, MINUTES, SECONDS)            
            time.sleep(interval)
            tempseconds = tempseconds - interval
            
    def cpu_bug_repair(self, slot):

        cmd = r'd 0xe00e00a4,1,4'
        rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), slot, DEV_PORT)
        if rtn_str == '':
            self.info_show(log_node_fail, log_connect_slot_fail%(self.get_ne_ip(0), slot))
            print "\n\nIP:%s,   The script can't connect slot %d!\n\n" % (self.get_ne_ip(0), slot)
            time.sleep(int(self.options.sleeptime))
        else:
            #得到当前寄存器中的值，注意有效位数
            version = (re.findall(r"0xe00e00a0:           (\w+|\d+)", rtn_str, re.I))[0]
            version = int(version,16)
            
            #是否需要CPU补丁
            if version == 0x80310020 :
                cmd = r'*0xe0001010&=~0x00010000'
                rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), slot, DEV_PORT)
            
                    
                #校验写入的值
                cmd = r'd 0xe0001010,1,4'
                rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), slot, DEV_PORT)
                
                #如果异常值，就退出
                if rtn_str == '':
                    return False
                
                version = (re.findall(r"0xe0001010:  (\w+|\d+)", rtn_str, re.I))[0]
                version = int(version,16)
                
                if version & 0x00010000 != 0:
                    #校验失败记录LOG
                    self.info_show(log_node_fail, log_cpu_fail%(self.get_ne_ip(0), slot, self.masterPPCSlot) )
                    self.info_show(log_node_summary, log_cpu_fail%(self.get_ne_ip(0), slot, self.masterPPCSlot) )
                    
                    return False
                else:
                    print "\n\nIP:%s,   Slot:%d , Opca's CPU repair removed success!\n\n" % (self.get_ne_ip(0), slot)
                    self.info_show(log_node_success, log_cpu_success%(self.get_ne_ip(0), slot, self.masterPPCSlot))
                    self.info_show(log_node_summary, log_cpu_success%(self.get_ne_ip(0), slot, self.masterPPCSlot) )
                    time.sleep(int(self.options.sleeptime))
            else:
                #记录LOG不需CPU补丁
                self.info_show(log_node_normal, log_cpu_no_need%(self.get_ne_ip(0), slot, self.masterPPCSlot))
                self.info_show(log_node_summary, log_cpu_no_need%(self.get_ne_ip(0), slot, self.masterPPCSlot) )
        
        return True
    
    def disable_second_iic(self, slot):
        cmd = r'd 0xe0003108,1,4'
        rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), slot, DEV_PORT)
        if rtn_str == '':
            self.info_show(log_node_fail, log_connect_slot_fail%(self.get_ne_ip(0), slot))
            print "\n\nIP:%s,   The script can't connect slot %d!\n\n" % (self.get_ne_ip(0), slot)
            time.sleep(int(self.options.sleeptime))
        else:
            cmd = r'*0xe0003108|=0xc0000000'
            rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), slot, DEV_PORT)
                
            #校验写入的值
            cmd = r'd 0xe0003108,1,4'
            rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), slot, DEV_PORT)
            
            #如果异常值，就退出
            if rtn_str == '':
                return False
            
            version = (re.findall(r"0xe0003100:                    (\w+|\d+)", rtn_str, re.I))[0]
            version = int(version,16)
            
            #等待确定
            if version != 0xc0c0c0c0:
                #IIC失败记录LOG
                self.info_show(log_node_fail, log_iic_fail%(self.get_ne_ip(0), slot, self.masterPPCSlot))
                self.info_show(log_node_summary, log_iic_fail%(self.get_ne_ip(0), slot, self.masterPPCSlot) )
                
                return False
            else:
                print "\n\nIP: %s,  Slot:%d ,Opca's IIC second group disabled removed success!\n\n" % (self.get_ne_ip(0), slot)
                self.info_show(log_node_success, log_iic_success%(self.get_ne_ip(0), slot, self.masterPPCSlot))
                self.info_show(log_node_summary, log_iic_success%(self.get_ne_ip(0), slot, self.masterPPCSlot) )
                time.sleep(int(self.options.sleeptime))
        return True               
                
    def _execute(self):
        self.work_path = self.options.path
        self.iplistfile = self.options.cfgfile
        
        self.info_init()
        
        worktime = str(datetime.datetime.now())
        self.worktime = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        self.info_show(log_node_summary, "The operation begin time %s \n"%(self.worktime))
        self.info_file_save()
        self.info_init()
        
        while True:
            if self.options.ipsource == "folder":
                ip_list = self.get_iplist_from_folder()
            else:
                ip_list = self.get_iplist_from_file()
            
            i = 0
            
            if ip_list != []:
                for ip in ip_list:
                    
                    #担心非IP.TXT的文件存在于该文件夹下面
                    if re.match(r"\d+.\d+.\d+.\d+", ip) == None:
                        print "\n\n %s is the wrong IP format!\n\n" % ip
                        i = i + 1
                        continue
                    
                    i = i + 1
                    
                    print "\n\nThere are total %d NE will remove repaired, current IP: %s. %d NE remained.\n\n" % (len(ip_list), ip,  len(ip_list) - i)
                    time.sleep(int(self.options.sleeptime))
                    
                    self.set_ne_ip(0, ip)
                    
                    #记录返回值
                    return_list = []
                    
                    #得到主用PPC槽位号
                    self.masterPPCSlot = self.getMasterPPC()
                    if self.masterPPCSlot not in [3,4] or self.masterPPCSlot == []:
                        print "\n\nTry the second time to query the masterPPCSlot!\n\n"
                        self.my_sleep(120,5)
                        self.masterPPCSlot = self.getMasterPPC()
                        if self.masterPPCSlot not in [3,4] or self.masterPPCSlot == []:
                            continue 
         
                    if not self.cpu_bug_repair(self.masterPPCSlot):
                        print "Active opca's CPU repair removed fail!\n"
                        return_list.append("False")
                    if not self.cpu_bug_repair(7 - self.masterPPCSlot):
                        print "Standby opca's CPU repair removed fail!\n"
                        return_list.append("False")
                    if not self.disable_second_iic(self.masterPPCSlot):
                        print "Active opca's IIC second group disabled removed fail!\n"
                        return_list.append("False")
                    if not self.disable_second_iic(7 - self.masterPPCSlot):
                        print "Standby opca's IIC second group disabled removed fail!\n"
                        return_list.append("False")
                    
                    if  return_list == []:
                        #成功处理完就删除文件,针对文件夹模式
                        if self.options.ipsource == "folder":
                            currentpath = os.getcwd()
                            os.chdir(self.options.path)
                            os.remove(ip+".txt")
                            os.chdir(currentpath)
                            
                        self.info_show(log_node_summary, log_cpu_iic_success%(self.get_ne_ip(0)))
                    else:
                        if  self.options.delete == "True":
                            #失败了删除文件,针对文件夹模式
                            if self.options.ipsource == "folder":
                                currentpath = os.getcwd()
                                os.chdir(self.options.path)
                                os.remove(ip+".txt")
                                os.chdir(currentpath)
                            
                        self.info_show(log_node_summary, log_cpu_iic_fail%(self.get_ne_ip(0)))
                        
                    self.info_file_save()
                    #每处理一个IP就保存下处理结果
                    self.info_init()
                    
                #文件模式下轮询完了退出
                if not self.options.ipsource == "folder":
                    break
            else:
                if self.options.quit == "True":
                    print "\n\nThe folder is empty! Quit the script!\n\n"
                    break
                
                print "\n\nThere is no ip.txt file, the script will check the folder again after %d s\n\n" % int(self.options.interval)
                self.my_sleep(int(self.options.interval), 5)
                
        worktime = str(datetime.datetime.now())
        self.worktime_end = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.info_show(log_node_summary, "The operation end time %s "%(self.worktime_end))

        self.info_file_save()
        
        return True
    
if __name__ == "__main__" :
    case = TestCase()
    case.execute()